﻿using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using SST.WebClient.Data;
using SST.WebClient;
using System.Windows.Threading;
using SST.WebClient.Util;
using SST.Phone.Util;
using SST.Phone.Model.DAO;
using SST.Phone.Model.VO;


namespace SST.Phone
{
    public class MainViewModel : INotifyPropertyChanged
    {
        /// <summary>
        /// Default refresh interval of now playing information in seconds
        /// </summary>
        public const int DEFAULT_NOW_PLAYING_REFRESH_INTERVAL = 30;
        /// <summary>
        /// Default refresh interval of now playing information in seconds
        /// </summary>
        public const int DEFAULT_CHAT_REFRESH_INTERVAL = 15;

        /// <summary>
        /// Uri to default album art file
        /// </summary>
        public const string DEFAULT_ALBUM_ART = "/Resources/album_cover_default.png";

        /// <summary>
        /// To trigger refresh now playing info and queue
        /// </summary>
        private DispatcherTimer nowPlayingRefreshTimer = new DispatcherTimer();

        /// <summary>
        /// To trigger refresh chat message list
        /// </summary>
        private DispatcherTimer chatRefreshTimer = new DispatcherTimer();

        public MainViewModel()
        {
            nowPlayingRefreshTimer.Tick += new EventHandler(nowPlayingRefreshTimer_Tick);
            chatRefreshTimer.Tick += new EventHandler(chatRefreshTimer_Tick);
            this.RequestQueueList = new ObservableCollection<StreamingRequest>();
            this.ChatList = new ObservableCollection<ChatMessage>();
            ChatRefreshTime = -1;
        }

        #region Properties
        private StreamingRequest _NowPlaying;
        /// <summary>
        /// The streaming request now playing
        /// </summary>
        public StreamingRequest NowPlaying
        {
            get { return _NowPlaying; }
            set
            {
                _NowPlaying = value;
                NotifyPropertyChanged("NowPlaying");
            }
        }

        private bool _IsPlaying;
        /// <summary>
        /// True if is playing
        /// </summary>
        public bool IsPlaying
        {
            get { return _IsPlaying; }
            set
            {
                _IsPlaying = value;
                NotifyPropertyChanged("IsPlaying");
            }
        }

        /// <summary>
        /// Queue request list
        /// </summary>
        public ObservableCollection<StreamingRequest> RequestQueueList { get; private set; }

        /// <summary>
        /// Chart message list
        /// </summary>
        public ObservableCollection<ChatMessage> ChatList { get; private set; }

        public bool IsDataLoaded
        {
            get;
            set;
        }

        private string _Message;
        /// <summary>
        /// Message shown right under title
        /// </summary>
        public string Message
        {
            get { return _Message; }
            set
            {
                _Message = value;
                NotifyPropertyChanged("Message");
            }
        }

        private bool _IsDownloadIndicatorVisible;
        /// <summary>
        /// Control show or hide download indicator
        /// </summary>
        public bool IsDownloadIndicatorVisible
        {
            get { return _IsDownloadIndicatorVisible; }
            set
            {
                _IsDownloadIndicatorVisible = value;
                NotifyPropertyChanged("IsDownloadIndicatorVisible");
            }
        }

        private UserAccount _User;
        /// <summary>
        /// User
        /// </summary>
        public UserAccount User
        {
            get { return _User; }
            set
            {
                _User = value;
                NotifyPropertyChanged("User");
            }
        }

        private bool _IsEnableChatSend;
        /// <summary>
        /// True to allow send chat message
        /// </summary>
        public bool IsEnableChatSend
        {
            get { return _IsEnableChatSend; }
            set
            {
                _IsEnableChatSend = value;
                NotifyPropertyChanged("IsEnableChatSend");
            }
        }

        private int _ChatRefreshTime;
        /// <summary>
        /// Chat refresh time
        /// </summary>
        public int ChatRefreshTime
        {
            get { return _ChatRefreshTime; }
            set
            {
                _ChatRefreshTime = value;
                NotifyPropertyChanged("ChatRefreshTime");
            }
        }

        private bool _ShowTray;
        /// <summary>
        /// Show or hide tray
        /// </summary>
        public bool ShowTray
        {
            get { return _ShowTray; }
            set
            {
                _ShowTray = value;
                NotifyPropertyChanged("ShowTray");
            }
        }

        /// <summary>
        /// Store number of things being downloaded, to control show/hide of downloading animation
        /// </summary>
        private DownloadingCounter DownloadingCounter = new DownloadingCounter();
        #endregion

        #region Load data
        /// <summary>
        /// Creates and adds a few ItemViewModel objects into the Items collection.
        /// </summary>
        public void LoadData()
        {
            //dummy request
            this.NowPlaying = new StreamingRequest()
            {
                Track = new Soundtrack()
                {
                    AlbumArt = DEFAULT_ALBUM_ART
                }
            };

            this.IsDataLoaded = true;

            //begin loading async data
            LoadNowPlaying();
            LoadQueue();
            LoadChatList();
        }

        /// <summary>
        /// Download now playing data
        /// </summary>
        public void LoadNowPlaying()
        {
            AddLoadingCount();

            NowPlayingInfo info = new NowPlayingInfo();
            info.GetAsyncCompleted += (s, e) =>
            {
                DeductLoadingCount();
                this.NowPlaying = e.Request;
                //prepare timer for the next fetch
                int timerInterval = 0;
                if (this.NowPlaying != null && this.NowPlaying.Track != null && this.NowPlaying.Track.Duration > 0)
                    timerInterval = this.NowPlaying.Track.Duration > 10 ? this.NowPlaying.Track.Duration - 10 : this.NowPlaying.Track.Duration;
                else
                    timerInterval = DEFAULT_NOW_PLAYING_REFRESH_INTERVAL;
                UIHelper.Debug("now playing timerInterval=" + timerInterval);
                
                nowPlayingRefreshTimer.Stop();
                nowPlayingRefreshTimer.Interval = TimeSpan.FromSeconds(timerInterval);
                nowPlayingRefreshTimer.Start();
            };
            info.GetAsync();
        }

        /// <summary>
        /// Download request queue
        /// </summary>
        public void LoadQueue()
        {
            AddLoadingCount();

            RequestQueueInfo info = new RequestQueueInfo();
            info.GetAsyncCompleted += (s, e) =>
            {
                DeductLoadingCount();
                this.RequestQueueList.Clear();
                foreach (var r in e.RequestList)
                {
                    //change to default album art if not filled
                    if (r.Track.AlbumArt == null)
                        r.Track.AlbumArt = DEFAULT_ALBUM_ART;
                    this.RequestQueueList.Add(r);
                }
            };
            info.GetAsync();
        }

        /// <summary>
        /// Download chat message list
        /// </summary>
        public void LoadChatList()
        {
            chatRefreshTimer.Stop();

            if (ChatRefreshTime == 0)
                return;

            //get chat refresh setting
            if (ChatRefreshTime == -1)
            {
                //get from database
                SettingsDAO settingDAO = new SettingsDAO(App.DB);
                string chatRefresh = settingDAO.LoadValue(SettingItem.SETTING.CHAT_REFRESH);
                try
                {
                    if (chatRefresh != null)
                        ChatRefreshTime = int.Parse(chatRefresh);
                    else
                    {
                        //set to default
                        ChatRefreshTime = DEFAULT_CHAT_REFRESH_INTERVAL;
                        settingDAO.Save(new SettingItem() { Name = SettingItem.SETTING.CHAT_REFRESH.ToString(), Value = ChatRefreshTime.ToString() });
                    }
                }
                catch (Exception ex)
                {
                    UIHelper.Debug(ex);
                    ChatRefreshTime = 0;
                }
                if (ChatRefreshTime == 0)
                    return;
            }

            AddLoadingCount();

            UIHelper.Debug("downloading chat");
            ChatService service = new ChatService();
            service.GetAsyncCompleted += (s, e) =>
            {
                DeductLoadingCount();
                this.ChatList.Clear();

                foreach (var r in e.ChatList)
                {
                    this.ChatList.Add(r);
                }

                //prepare timer for the next fetch
                int timerInterval = ChatRefreshTime;
                UIHelper.Debug("now chat timerInterval=" + timerInterval);

                chatRefreshTimer.Interval = TimeSpan.FromSeconds(timerInterval);
                chatRefreshTimer.Start();
            };
            service.GetAsync();
        }
        #endregion

        #region Loading count
        /// <summary>
        /// Increment the loading count
        /// </summary>
        public void AddLoadingCount()
        {
            lock (DownloadingCounter)
            {
                DownloadingCounter.Count++;
                IsDownloadIndicatorVisible = true;
            }
        }

        /// <summary>
        /// Decrement the loading count
        /// </summary>
        public void DeductLoadingCount()
        {
            lock (DownloadingCounter)
            {
                DownloadingCounter.Count--;
                //hide downloading if all downloaded
                if (DownloadingCounter.Count <= 0)
                {
                    DownloadingCounter.Count = 0;
                    IsDownloadIndicatorVisible = false;
                }
            }
        }
        #endregion

        /// <summary>
        /// Timer trigger refresh now playing and queue data
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void nowPlayingRefreshTimer_Tick(object sender, EventArgs e)
        {
            UIHelper.Debug("nowPlayingRefreshTimer_Tick");
            nowPlayingRefreshTimer.Stop();
            LoadNowPlaying();
            LoadQueue();
        }

        /// <summary>
        /// Timer trigger refresh chat message
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void chatRefreshTimer_Tick(object sender, EventArgs e)
        {
            UIHelper.Debug("chatRefreshTimer_Tick");
            chatRefreshTimer.Stop();
            LoadChatList();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (null != handler)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    /// <summary>
    /// Keep number of download request being processed
    /// </summary>
    public class DownloadingCounter
    {
        private int _Count;

        public int Count
        {
            get { return _Count; }
            set { _Count = value; }
        }
    }
}